﻿using System;
using System.Collections.Specialized;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Factory;

/// <summary>
/// <see cref="NameValueCollectionConvertor{T}"/> 工厂
/// </summary>
public sealed class NameValueCollectionConvertorFactory : IConvertorFactory
{
    /// <inheritdoc/>
    public MatchedConvertor<T> Create<T>()
    {

        var type = typeof(T);

        switch (type.MatchType(typeof(NameValueCollection), typeof(NameValueCollection)))
        {
            case MacthedType.Equals:
                var convertor1 = (IConvertor<T>)Activator.CreateInstance(typeof(NameValueCollectionConvertor<>).MakeGenericType(type));
                return new MatchedConvertor<T>(convertor1, MacthedType.Equals);
            case MacthedType.Acceptable:
                if (typeof(NameValueCollection).IsAssignableFrom(type))
                {
                    var convertor2 = (IConvertor<T>)Activator.CreateInstance(typeof(NameValueCollectionConvertor<>).MakeGenericType(type));
                    return new MatchedConvertor<T>(convertor2, MacthedType.Acceptable);
                }
                else if (typeof(NameObjectCollectionBase) == type)
                {
                    var convertor2 = new NameValueCollectionConvertor<NameValueCollection>();
                    var proxy = (IConvertor<T>)Activator.CreateInstance(typeof(ProxyConvertor<,>).MakeGenericType(typeof(NameValueCollection), typeof(T)), convertor2);
                    return new MatchedConvertor<T>(proxy, MacthedType.Acceptable);
                }
                break;
            case MacthedType.TryCreate:
                var convertor3 = (IConvertor<T>)Activator.CreateInstance(typeof(NameValueCollectionConvertor<>).MakeGenericType(type));
                return new MatchedConvertor<T>(convertor3, MacthedType.TryCreate);
            case MacthedType.NotMatched:
            default:
                break;
        }

        return default;
    }
}
